﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using PMisuseAn.util;
using System.Collections;
using PMisuseAn.io;

namespace PMisuseAn.behaviour.model
{
    public class ApplicableIfTest
    {
        public static bool applicableIfAnalysis(Agent sendAgent, Agent receiveAgent, Agent subjectAgent, State message_s, Transition message_t, List<Object> parameterisedContextInstances,
                                            PolicyStatementAnalyser statAnalyser, Context contextInstance)
        {
            bool attributeFunctionActive = false;
            bool groupFunctionActive = false;

            string lastEntity = "";
            string lastEntityType = "";
            string joinOperator = "";
            string symbol = "";

            ListDictionary contextItems = new ListDictionary();
            ListDictionary aggContextItems = new ListDictionary();

            int newKey = HistorySerialisationEngine.totalInteractions();

            foreach (DictionaryEntry policyItem in statAnalyser.tokenisedIfContent)
            {
                int pol_id = (int)policyItem.Key;

                Dictionary<string, string> word_m = (Dictionary<string, string>)policyItem.Value;

                foreach (KeyValuePair<string, string> pair in word_m)
                {
                    string type = pair.Key;
                    string word = pair.Value;
                    if (type.Equals("functionalAttribute"))
                    {
                        bool found = false;
                        if (message_s != null)
                        {
                            if (message_s.name.Equals(word))
                            {
                                attributeFunctionActive = true;
                                contextItems.Add(newKey, true);
                                newKey = newKey + 1;
                                found = true;
                                lastEntity = word;
                                lastEntityType = type;
                            }
                        }
                        else if (message_t != null)
                        {
                            string endState = message_t.endState;
                            if (endState.Equals(word))
                            {
                                attributeFunctionActive = true;
                                found = true;
                                contextItems.Add(newKey, true);
                                newKey = newKey + 1;
                                lastEntity = word;
                                lastEntityType = type;
                            }
                        }

                        if (!found)
                        {
                            contextItems.Add(newKey, false);
                            newKey = newKey + 1;
                        }
                    }
                    else if (type.Equals("policyFunction"))
                    {
                        bool found = false;

                        attributeFunctionActive = true;
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        found = true;
                        lastEntity = word;
                        lastEntityType = type;
                    }
                    else if (type.Equals("attribute"))
                    {
                        bool found = false;
                        foreach (Object obj in parameterisedContextInstances)
                        {
                            Attribute att = obj as Attribute;
                            if (att != null)
                            {
                                if (att.name.Equals(word))
                                {
                                    contextItems.Add(newKey, true);
                                    newKey = newKey + 1;
                                    found = true;
                                    lastEntity = word;
                                    lastEntityType = type;
                                    break;
                                }
                            }
                        }
                        if (!found)
                        {
                            contextItems.Add(newKey, false);
                            newKey = newKey + 1;
                        }
                    }
                    
                    else if (type.Equals("number"))
                    {
                        double number;
                        if (Double.TryParse(word, out number))
                        {
                            double word_val = Convert.ToDouble(word);

                            if (lastEntityType.Equals("attribute"))
                            {
                                bool found = false;
                                foreach (Object obj in parameterisedContextInstances)
                                {
                                    Attribute att = obj as Attribute;
                                    if (att != null)
                                    {
                                        if (symbol.Equals("="))
                                        {
                                            if (att.name.Equals(lastEntity))
                                            {
                                                if (Double.TryParse(att.activeDomain, out number))
                                                {
                                                    double att_dom_val = Convert.ToDouble(att.activeDomain);
                                                    if (att_dom_val == word_val)
                                                    {
                                                        contextItems.Add(newKey, true);
                                                        newKey = newKey + 1;
                                                        found = true;
                                                        break;
                                                    }
                                                }

                                            }
                                        }
                                        else if (symbol.Equals("≠"))
                                        {
                                            if (att.name.Equals(lastEntity))
                                            {
                                                if (Double.TryParse(att.activeDomain, out number))
                                                {
                                                    double att_dom_val = Convert.ToDouble(att.activeDomain);
                                                    if (att_dom_val != word_val)
                                                    {
                                                        contextItems.Add(newKey, true);
                                                        newKey = newKey + 1;
                                                        found = true;
                                                        break;
                                                    }
                                                }

                                            }
                                        }
                                        else if (symbol.Equals("&lt;"))
                                        {
                                            if (att.name.Equals(lastEntity))
                                            {
                                                if (Double.TryParse(att.activeDomain, out number))
                                                {
                                                    double att_dom_val = Convert.ToDouble(att.activeDomain);
                                                    if (att_dom_val < word_val)
                                                    {
                                                        contextItems.Add(newKey, true);
                                                        newKey = newKey + 1;
                                                        found = true;
                                                        break;
                                                    }
                                                }

                                            }
                                        }
                                        else if (symbol.Equals(">"))
                                        {
                                            if (att.name.Equals(lastEntity))
                                            {
                                                if (Double.TryParse(att.activeDomain, out number))
                                                {
                                                    double att_dom_val = Convert.ToDouble(att.activeDomain);
                                                    if (att_dom_val > word_val)
                                                    {
                                                        contextItems.Add(newKey, true);
                                                        newKey = newKey + 1;
                                                        found = true;
                                                        break;
                                                    }
                                                }

                                            }
                                        }
                                    }
                                }
                                if (!found)
                                {
                                    contextItems.Add(newKey, false);
                                    newKey = newKey + 1;
                                }
                            }
                        }
                    }

                    else if (type.Equals("string"))
                    {
                        bool found = false;
                        if (lastEntityType.Equals("attribute"))
                        {
                            foreach (Object obj in parameterisedContextInstances)
                            {
                                Attribute att = obj as Attribute;
                                if (att != null)
                                {
                                    if (symbol.Equals("="))
                                    {
                                        if (att.name.Equals(lastEntity))
                                        {
                                            if (att.activeDomain.Equals(word))
                                            {
                                                contextItems.Add(newKey, true);
                                                newKey = newKey + 1;
                                                found = true;
                                                break;
                                            }
                                        }
                                    }
                                    else if (symbol.Equals("≠"))
                                    {
                                        if (att.name.Equals(lastEntity))
                                        {
                                            if (!att.activeDomain.Equals(word))
                                            {
                                                contextItems.Add(newKey, true);
                                                newKey = newKey + 1;
                                                found = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else if (lastEntityType.Equals("receiver"))
                        {
                            //foreach (Object obj in parameterisedContextInstances)
                            //{
                                if (symbol.Equals("="))
                                {
                                    if (receiveAgent.agentName.Equals(word))
                                    {
                                        contextItems.Add(newKey, true);
                                        newKey = newKey + 1;
                                        found = true;
                                        //break;
                                    }
                                }
                                else if (symbol.Equals("≠"))
                                {
                                    if (!receiveAgent.agentName.Equals(word))
                                    {
                                        contextItems.Add(newKey, true);
                                        newKey = newKey + 1;
                                        found = true;
                                        //break;
                                    }
                                }

                            //}
                        }
                        else if (lastEntityType.Equals("sender"))
                        {
                            //foreach (Object obj in parameterisedContextInstances)
                            //{
                                if (symbol.Equals("="))
                                {
                                    if (sendAgent.agentName.Equals(word))
                                    {
                                        contextItems.Add(newKey, true);
                                        newKey = newKey + 1;
                                        found = true;
                                        //break;
                                    }
                                }
                                else if (symbol.Equals("≠"))
                                {
                                    if (!sendAgent.agentName.Equals(word))
                                    {
                                        contextItems.Add(newKey, true);
                                        newKey = newKey + 1;
                                        found = true;
                                        //break;
                                    }
                                }
                            //}
                        }
                        else if (lastEntityType.Equals("subject"))
                        {
                            //foreach (Object obj in parameterisedContextInstances)
                            //{
                                if (symbol.Equals("="))
                                {
                                    if (subjectAgent.agentName.Equals(word))
                                    {
                                        contextItems.Add(newKey, true);
                                        newKey = newKey + 1;
                                        found = true;
                                        //break;
                                    }
                                }
                                else if (symbol.Equals("≠"))
                                {
                                    if (!subjectAgent.agentName.Equals(word))
                                    {
                                        contextItems.Add(newKey, true);
                                        newKey = newKey + 1;
                                        found = true;
                                        //break;
                                    }
                                }
                            //}
                        }
                        if (!found)
                        {
                            contextItems.Add(newKey, false);
                            newKey = newKey + 1;
                        }
                    }
                    else if (type.Equals("and"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        joinOperator = word;
                        aggContextItems.Add(contextItems, word);
                        contextItems = new ListDictionary();
                    }
                    else if (type.Equals("or"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        joinOperator = word;
                        aggContextItems.Add(contextItems, word);
                        contextItems = new ListDictionary();
                    }
                    else if (type.Equals("sender"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        lastEntityType = type;
                        lastEntity = word;
                    }
                    else if (type.Equals("lessthan") || type.Equals("greaterthan") || type.Equals("equals") || type.Equals("notequals"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        symbol = word;
                    }
                    else if (type.Equals("receiver"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        lastEntityType = type;
                        lastEntity = word;
                    }
                    else if (type.Equals("subject"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                        lastEntityType = type;
                        lastEntity = word;
                    }
                    else if (type.Equals("groupFunction"))
                    {
                        //TODO: groupfunction functional check
                        bool found = false;
                        foreach (Object obj in parameterisedContextInstances)
                        {
                            GroupFunction gf = obj as GroupFunction;
                            if (gf != null)
                            {
                                if (gf.functionName.Equals(word))
                                {
                                    groupFunctionActive = true;
                                    contextItems.Add(newKey, true);
                                    newKey = newKey + 1;
                                    found = true;
                                    lastEntityType = type;
                                    lastEntity = word;
                                    break;
                                }
                            }
                        }
                        if (!found)
                        {
                            contextItems.Add(newKey, false);
                            newKey = newKey + 1;
                        }
                    }
                    else if (type.Equals("openingBracket"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                    }
                    else if (type.Equals("comma"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                    }
                    else if (type.Equals("closingBracket"))
                    {
                        if (attributeFunctionActive)
                        {
                            attributeFunctionActive = false;
                        }
                        else if (groupFunctionActive)
                        {
                            groupFunctionActive = false;
                        }

                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                    }
                    else if (type.Equals("closingsquarebracket"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                    }
                    else if (type.Equals("openingsquarebracket"))
                    {
                        contextItems.Add(newKey, true);
                        newKey = newKey + 1;
                    }
                }
            }
            if (aggContextItems.Contains(contextItems))
            {
                ListDictionary dic = new ListDictionary();
                foreach (DictionaryEntry pair in contextItems)
                {
                    dic.Add(pair.Key, pair.Value);
                }
                aggContextItems.Add(dic, "NOJOIN");
            }
            else
            {
                aggContextItems.Add(contextItems, "NOJOIN");

            }

            bool applicableIFSegment = false;

            foreach (DictionaryEntry contextItemkv in aggContextItems)
            {
                ListDictionary contextItem = (ListDictionary)contextItemkv.Key;
                string jointype = (string)contextItemkv.Value;
                bool fault = false;
                foreach (DictionaryEntry item in contextItem)
                {
                    bool val = (bool)item.Value;
                    if (val == false)
                    {
                        fault = true;
                    }
                }

                if (fault == false)
                {
                    applicableIFSegment = true;
                }
                else
                {
                    applicableIFSegment = false;
                }

                if (jointype.Equals("∧") && applicableIFSegment == false)
                {
                    break;
                }
                else if (jointype.Equals("∧") && applicableIFSegment == true)
                {
                    //continue;
                }
                else if (jointype.Equals("V") && applicableIFSegment == true)
                {
                    break;
                }
                else if (jointype.Equals("V") && applicableIFSegment == false)
                {
                    //continue;
                }

            }
            return applicableIFSegment;
        }


    }
}
